home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / lo_pas.com / UNIT123.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1989-05-27  |  17.2 KB  |  510 lines

  1. {$N+,E+}  (*  $N+ compiles for 80x87 which is used                 *)
  2.           (*  automatically if available.  E+ activates the        *)
  3.           (*  80X87 emulator which will be used if a coprocessor   *)
  4.           (*  is not present.  I understand that these are program *)
  5.           (*  wide options and cannot be used in a unit separately *)
  6.  
  7. (*  Written by Dan Glanz, Alexandria, Virginia (76672,2572), May, 1989. *)
  8. (*  as a public service.                                                *)
  9. (*  There are no restrictions on use and no gaurantees that it works.   *)
  10.  
  11. (*    All I ask is a smidgeon of credit.                          *)
  12. (*  If you include this in a program, leave the credit line in. *)
  13. (*  If you modify the unit, add your own credit line.           *)
  14.  
  15. (*    This is a Turbo Pascal 5.0 unit designed to allow reading and writing
  16.     of Lotus 1-2-3,    Symphony, VP-Planner and other such files using the
  17.     Lotus 1-2-3    file format.
  18.  
  19.     Lotus 1-2-3 uses 8 byte reals (TP's double's).  Any program using
  20.     Lotus 1-2-3 data must either use a math coprocessor {$N+} or
  21.     coprocessor emulation {$N+,E+}
  22.  
  23.     For demonstration purposes, a separate program called TEST123
  24.     is included in the ARC file.
  25.  
  26.     It reads any Lotus format file and copies out label, integer and real
  27.     cells and the current value of formula cells to a file in the same
  28.     directory with the same name but with an extension of '.WK!'
  29.     It does not copy formulas, range names, and other such information.
  30.     It is purely designed to allow access to the DATA.
  31.  
  32.     Incidentally, you may be amazed at how fast a file loads when all
  33.     of the blank cells, formulas, etc. have been removed by this
  34.     program.
  35.  
  36.     Lotus_Version is set up as a typed constant as if the file were
  37.     a Lotus version 1.0 or 1a type file.  Change it if you need to.
  38.     The program automatically writes a version record at the beginning of
  39.     the file when the file is opened for writing by calling
  40.     Open_Lotus_Write_File.  It must do this or Lotus 1-2-3 will not
  41.     allow use of the file.  The actual version read in from another file is
  42.     ignored in this unit.  Obviously this can be changed.
  43.  
  44.     If you want to use the unit to create a Lotus formatted file directly,
  45.     you must provide the row and column of the data in Lotus.Row and
  46.     Lotus.Column, define the format in Lotus.Format (default seems to be 255)
  47.     set the value in either Lotus.Integer_Value, Lotus.Real_Value, or
  48.     Lotus.Label_Value.  Then set Lotus.Cell_Type := to Integer_Type,
  49.     Real_Type, or Label_Type as the case may be    and call Write_Lotus_Record.
  50.  
  51.     Note: When you write your own labels in Label_Value, make sure you put
  52.     a ' or " or ^ as the first character of the string.  Also, you may be
  53.     able to include formulas in a worksheet you are creating by writing out
  54.     a label cell containing with the formula and then deleting
  55.     the ', ", or ^ in the spreadsheet itself, perhaps by using a macro.
  56.  
  57.     When you call Close_Lotus_Write_File, an end of file record is written
  58.     and the file is automatically closed.
  59.  
  60.     Lotus 1-2-3 is a trademark of Lotus Corporation.
  61.  
  62. *)
  63.  
  64. Unit Unit123;
  65. Interface
  66.  
  67. uses crt, dos;
  68.  
  69. Const
  70.     Lotus_Version : integer = 1028;  {1028 for Lotus 1}
  71.                                      {1029 for Symphony 1.0}
  72.                                      {1030 for Lotus 2 & Symphony 1.1}
  73.  
  74. Type
  75.     Lotus_Cell_Type = (Version_Type, End_Of_File_Type, Blank_Type,
  76.                        Integer_Type, Real_Type, Label_Type,
  77.                        Formula_Type, Unidentified_Type);
  78.  
  79.     Lotus_Record_Type =
  80.         Record
  81.             Cell_Type       : Lotus_Cell_Type;
  82.             Cell_Type_Code    : Integer;
  83.             Cell_Length        : Integer;
  84.             Format            : Byte;
  85.             Column            : integer;
  86.             Row                : integer;
  87.             Integer_Value    : integer;
  88.             Real_Value        : double;
  89.             Label_Value        : string;
  90.             Formula_Length  : integer;
  91.             Formula            : array [0 .. 255] of byte;
  92.             Unidentified    : array [0 .. 511] of byte;
  93.             Zero            : byte;     {used to terminate labels - ASCII-Z}
  94.         end;
  95. var
  96.     Lotus_Read_File_Name    : string;
  97.     Lotus_Read_File         : file;
  98.  
  99.     Lotus_Write_File_Name    : string;
  100.     Lotus_Write_File        : file;
  101.  
  102.     Lotus_End_Of_File        : boolean;
  103.     Lotus_Version_Name        : string;
  104.  
  105.     Lotus                    : Lotus_Record_Type;
  106.  
  107. Procedure Open_Lotus_Read_File;
  108. Procedure Get_Version_Name;
  109. Procedure Read_Type_and_Length;
  110. Procedure Read_Format_Info;
  111. Procedure Read_Lotus_Record;
  112. Procedure Print_Lotus_Record;
  113. Procedure Close_Lotus_Read_File;
  114.  
  115. Procedure Make_New_File_Name;
  116. Procedure Open_Lotus_Write_File;
  117. Procedure Write_Type_and_Length;
  118. Procedure Write_Format_Info;
  119. Procedure Write_Lotus_Record;
  120. Procedure Close_Lotus_Write_File;
  121.  
  122. implementation
  123.  
  124. (****************************************************************)
  125.  
  126. Procedure Read_Type_and_Length;    {Could be changed to a single }
  127.                                    {BlockRead since Cell_Type_Code}
  128.                                    {Cell_Length are adjacent in the record}
  129.                                    {definition and on the file.}
  130. begin
  131.     BlockRead(Lotus_Read_File, Lotus.Cell_Type_Code, 2);
  132.     BlockRead(Lotus_Read_File, Lotus.Cell_Length,    2);
  133.  
  134. {   OPTIONAL}
  135. {   BlockRead(Lotus_Read_File, Lotus.Cell_Type_Code, 4);   }
  136.  
  137. end;
  138.  
  139. (****************************************************************)
  140.  
  141. Procedure Write_Type_and_Length;        {Could be changed to a single }
  142.                                         {BlockWrite since format, column}
  143.                                         {and row are adjacent in the record}
  144.                                         {definition and on the file.}
  145. begin
  146.     BlockWrite(Lotus_Write_File, Lotus.Cell_Type_Code, 2);
  147.     BlockWrite(Lotus_Write_File, Lotus.Cell_Length,    2);
  148.  
  149. {   OPTIONAL}
  150. {   BlockWrite(Lotus_Write_File, Lotus.Cell_Type_Code, 4);   }
  151.  
  152. end;
  153.  
  154. (****************************************************************)
  155.  
  156. Procedure Read_Format_Info;             {Could be changed to a single }
  157.                                         {BlockRead since format, column}
  158.                                         {and row are adjacent in the record}
  159.                                         {definition and on the file.}
  160. begin
  161.     BlockRead(Lotus_Read_File, Lotus.Format, 1);
  162.     BlockRead(Lotus_Read_File, Lotus.Column, 2);
  163.     BlockRead(Lotus_Read_File, Lotus.Row,    2);
  164.  
  165. {   OPTIONAL}
  166. {   BlockRead(Lotus_Read_File, Lotus.Format, 5);   }
  167.  
  168. end;
  169.  
  170. (****************************************************************)
  171.  
  172. Procedure Write_Format_Info;            {Could be changed to a single }
  173.                                         {BlockWrite since format, column}
  174.                                         {and row are adjacent in the record}
  175.                                         {definition and on the file.}
  176. begin
  177.     BlockWrite(Lotus_Write_File, Lotus.Format, 1);
  178.     BlockWrite(Lotus_Write_File, Lotus.Column, 2);
  179.     BlockWrite(Lotus_Write_File, Lotus.Row,    2);
  180.  
  181. {   OPTIONAL}
  182. {   BlockWrite(Lotus_Write_File, Lotus.Format, 5);   }
  183.  
  184. end;
  185.  
  186. (****************************************************************)
  187.  
  188. Procedure Open_Lotus_Read_File;
  189. begin
  190. {$I-}
  191.     Assign(Lotus_Read_File,Lotus_Read_File_Name);
  192.     Reset(Lotus_Read_File,1);
  193.     If IoResult <> 0 then
  194.         begin
  195.             Writeln('Error opening file ', Lotus_Read_File_Name);
  196.             halt;
  197.         end;
  198. {$I+}
  199.      Read_Lotus_Record;                      {Read the first record}
  200.                                              {If the first record is}
  201.                                              {not a Version_Type record}
  202.                                              {then this is not a Lotus File}
  203.  
  204.     If Lotus.Cell_Type <> Version_Type then
  205.        begin
  206.             Writeln('This is not a Lotus File');
  207.             Halt
  208.        end;
  209.  
  210.     Lotus_End_Of_File := false;
  211. end;
  212.  
  213. (****************************************************************)
  214.  
  215. Procedure Open_Lotus_Write_File;
  216. begin
  217. {$I-}
  218.     Assign(Lotus_Write_File,Lotus_Write_File_Name);
  219.     ReWrite(Lotus_Write_File,1);
  220.     If IoResult <> 0 then
  221.         begin
  222.             Writeln('Error opening file ', Lotus_Write_File_Name);
  223.             halt;
  224.         end;
  225. {$I+}
  226.  
  227. { Automatically write a version type record at the beginning of the file }
  228. { Lotus_Version is a typed constant set to Version 1.0 or 1A by default  }
  229. { If you have used Open_Lotus_File to read another Lotus file, then it   }
  230. { will have already read the version type record from the input file     }
  231.  
  232.     Lotus.Cell_Type_Code := 0;
  233.     Lotus.Cell_Length    := 2;
  234.     Write_Type_and_Length;
  235.     BlockWrite(Lotus_Write_File,Lotus_Version,2);
  236.  
  237. end;
  238.  
  239. (****************************************************************)
  240.  
  241. Procedure Close_Lotus_Read_File;
  242. begin
  243.     Close(Lotus_Read_File);
  244. end;
  245.  
  246. (****************************************************************)
  247.  
  248. Procedure Close_Lotus_Write_File;
  249. begin
  250. { Write an end of file record at the end of the file }
  251.     Lotus.Cell_Type_Code := 1;
  252.     Lotus.Cell_Length    := 0;
  253.     Write_Type_and_Length;            {End the file with a type 1 record}
  254.     Close(Lotus_Write_File);
  255. end;
  256.  
  257. (****************************************************************)
  258.  
  259. Procedure Get_Version_Name;
  260. begin
  261.     Case Lotus_Version of
  262.         1028:
  263.             Lotus_Version_Name := 'Lotus 1-2-3 Version 1.0 or 1A';
  264.         1029:
  265.             Lotus_Version_Name := 'Symphony Version 1.0';
  266.         1030:
  267.             Lotus_Version_Name := 'Lotus 1-2-3 Version 2.0, 2.1 or Symphony Version 1.1';
  268.         Else
  269.             Lotus_Version_Name := 'Unidentified';
  270.     end;
  271. end;
  272.  
  273. (****************************************************************)
  274.  
  275. Procedure Read_Lotus_Record;
  276. begin
  277.     FillChar(Lotus, SizeOf(Lotus), #0);
  278.     Read_Type_and_Length;
  279.  
  280.     Case Lotus.Cell_Type_Code of
  281.  
  282.         0:  begin                             {Version Record}
  283.                                               {There should be only one}
  284.                                               {record of this type and it}
  285.                                               {will normally be read when}
  286.                                               {you call Open_Lotus_Read_File}
  287.  
  288.                 Lotus.Cell_Type := Version_Type;
  289.                 BlockRead(Lotus_Read_File, Lotus_Version, 2);
  290.                 Get_Version_Name;
  291.             end;
  292.  
  293.         1:  begin                                        {End of File}
  294.                 Lotus.Cell_Type := End_Of_File_Type;
  295.                 Lotus_End_of_File := True;
  296.             end;
  297.  
  298.         12: begin                                        {Blank Record}
  299.                 Lotus.Cell_Type := Blank_Type;
  300.                 Read_Format_Info;
  301.             end;
  302.  
  303.         13: begin                                         {Integer}
  304.                 Lotus.Cell_Type := Integer_Type;
  305.                 Read_Format_Info;
  306.                 BlockRead(Lotus_Read_File, Lotus.Integer_Value, 2);
  307.             end;
  308.  
  309.         14: begin                                         {Real Value}
  310.                 Lotus.Cell_Type := Real_Type;
  311.                 Read_Format_Info;
  312.                 BlockRead(Lotus_Read_File, Lotus.Real_Value, 8);
  313.             end;
  314.  
  315.         15: begin                                         {Label}
  316.                 Lotus.Cell_Type := Label_Type;
  317.                 Read_Format_Info;
  318.                 If Lotus.Cell_Length > 261 then
  319.                     begin
  320.                        Writeln('Big problem! Label at Row', Lotus.Row, ' Column ', Lotus.Column, ' has length > 255');
  321.                        Halt;
  322.                     end;
  323.                 BlockRead(Lotus_Read_File, Lotus.Formula, Lotus.Formula_Length);
  324.                 BlockRead(Lotus_Read_File, Lotus.Label_Value[1], Lotus.Cell_Length - 6);
  325.                 Lotus.Label_Value[0] := char(Lotus.Cell_Length - 6);
  326.                 BlockRead(Lotus_Read_File, Lotus.Zero, 1);
  327.             end;
  328.  
  329.         16: begin                                         {Formula}
  330.                 Lotus.Cell_Type := Formula_Type;
  331.                 Read_Format_Info;
  332.                 BlockRead(Lotus_Read_File, Lotus.Real_Value, 8);
  333.                 BlockRead(Lotus_Read_File, Lotus.Formula_Length, 2);
  334.                 If Lotus.Formula_Length > 255 then
  335.                     begin
  336.                        Writeln('Big problem! Formula cell at Row', Lotus.Row, ' Column ', Lotus.Column, ' has length > 255');
  337.                        Halt;
  338.                     end;
  339.                 BlockRead(Lotus_Read_File, Lotus.Formula, Lotus.Formula_Length);
  340.             end;
  341.  
  342.         Else                                              {Unidentified}
  343.             begin
  344.                 Lotus.Cell_Type := Unidentified_Type;
  345.  
  346.             {    Use the following line only if you are sure that the length }
  347.             {    of the unidentified data type is less than 512 characters.  }
  348.             {    I the unidentified data cell is more than 512 byte long,    }
  349.             {    it could cream the program by overwriting code.             }
  350.             {    The check on cell length protects against this. But,        }
  351.             {    if you don't know the maximum cell length, the safest       }
  352.             {    approach is the approach I have taken, just skip the        }
  353.             {    unknown data cell                                           }
  354.             {                                                                }
  355.             {    Read_Format_Info;                                           }
  356.             {                                                                }
  357.             {    If Lotus.Cell_Length > 512 then                             }
  358.             {        begin                                                   }
  359.             {           Writeln('Big problem! Cell at row ', Lotus.Row, ' Column ', Lotus.Coulmn, ' has  length > 512');   }
  360.             {           Halt;                                                }
  361.             {        end;                                                    }
  362.             {                                                                }
  363.             {    BlockRead (Lotus_Read_File, Lotus.Unidentified , Lotus.Cell_Length-5);}
  364.  
  365.  
  366.             {    This is the safest way.}
  367.  
  368.                 Seek(Lotus_Read_File, FilePos(Lotus_Read_File) + Lotus.Cell_Length);
  369.  
  370.             end;
  371.         end;
  372. end;
  373.  
  374. (****************************************************************)
  375.  
  376. Procedure Print_Lotus_Record;
  377. begin
  378.     If Lotus.Cell_Type = Blank_Type then exit;  {If you really want to}
  379.                                                 {show all of the blank}
  380.                                                 {records, delete this line}
  381.     Writeln;
  382.     Case Lotus.Cell_Type of
  383.  
  384.         Version_Type:
  385.             Writeln(Lotus_Version_Name, ' Id Code = ',Lotus_Version);
  386.  
  387.         End_Of_File_Type:
  388.             Writeln('End of File');
  389.  
  390.         Blank_Type:
  391.             begin
  392.                 Write('Row = ',Lotus.Row,' Column = ', Lotus.Column, ' Format = ',Lotus.Format);
  393.                 Writeln(' Blank Cell');
  394.             end;
  395.  
  396.         Integer_Type:
  397.             begin
  398.                 Write('Row = ',Lotus.Row,' Column = ', Lotus.Column, ' Format = ',Lotus.Format);
  399.                 Writeln(' Integer = ', Lotus.Integer_Value);
  400.             end;
  401.  
  402.         Real_Type:
  403.             begin
  404.                 Write('Row = ',Lotus.Row,' Column = ', Lotus.Column, ' Format = ',Lotus.Format);
  405.                 Writeln(' Real = ', Lotus.Real_Value);
  406.             end;
  407.  
  408.         Label_Type:
  409.             begin
  410.                 Writeln('Row = ',Lotus.Row,' Column = ', Lotus.Column, ' Format = ',Lotus.Format);
  411.                 Writeln('Label = ', Lotus.Label_Value);
  412.             end;
  413.  
  414.         Formula_Type:
  415.             begin
  416.                 Write('Row = ',Lotus.Row,' Column = ', Lotus.Column, ' Format = ',Lotus.Format);
  417.                 Writeln(' Formula Value = ', Lotus.Real_Value);
  418.             end;
  419.  
  420.         End_Of_File_Type:
  421.             Writeln('End of file detected.');
  422.  
  423.         Unidentified_Type:
  424.             begin
  425.                 Write('Row = ',Lotus.Row,' Column = ', Lotus.Column, ' Format = ',Lotus.Format);
  426.                 Writeln(' Unidentified Cell. OpCode = ', Lotus.Cell_Type_Code);
  427.             end;
  428.  
  429.         Else
  430.             begin
  431.                 Write('Row = ',Lotus.Row,' Column = ', Lotus.Column, ' Format = ',Lotus.Format);
  432.                 Writeln(' Unidentified Cell. OpCode = ', Lotus.Cell_Type_Code);
  433.             end;
  434.         end;
  435.  
  436. end;
  437.  
  438. (****************************************************************)
  439.  
  440. Procedure Write_Lotus_Record;
  441.  
  442. begin
  443.     Case Lotus.Cell_Type of
  444.  
  445.         Blank_Type:
  446.             Exit;
  447.  
  448.         Integer_Type:
  449.             begin
  450.                 Lotus.Cell_Type_Code := 13;
  451.                 Lotus.Cell_Length := 7;
  452.                 Write_Type_and_Length;
  453.                 Write_Format_Info;
  454.                 BlockWrite(Lotus_Write_File,Lotus.Integer_Value,2);
  455.             end;
  456.  
  457.         Real_Type:
  458.             begin
  459.                 Lotus.Cell_Type_Code := 14;
  460.                 Lotus.Cell_Length := 13;
  461.                 Write_Type_and_Length;
  462.                 Write_Format_Info;
  463.                 BlockWrite(Lotus_Write_File,Lotus.Real_Value,8);
  464.             end;
  465.  
  466.         Label_Type:
  467.             begin
  468.                 Lotus.Cell_Type_Code := 15;
  469.                 Lotus.Cell_Length := 6 + Length(Lotus.Label_Value);
  470.                 Lotus.Zero := 0;
  471.                 Write_Type_and_Length;
  472.                 Write_Format_Info;
  473.                 BlockWrite(Lotus_Write_File,Lotus.Label_Value[1],Length(Lotus.Label_Value));
  474.                 BlockWrite(Lotus_Write_File,Lotus.Zero, 1);
  475.             end;
  476.  
  477.         Formula_Type:    {NOTE: ONLY COPIES OUT THE CURRENT VALUE AS A REAL}
  478.                          { If you want to copy the formula then also       }
  479.                          { BlockWrite Lotus.Formula_Value.                 }
  480.                          { See Read_Lotus_File for how to interpret length }
  481.                          { Also, you must change the Cell_Type_Code to 16  }
  482.             begin
  483.                 Lotus.Cell_Type_Code := 14;
  484.                 Lotus.Cell_Length := 13;
  485.                 Write_Type_and_Length;
  486.                 Write_Format_Info;
  487.                 BlockWrite(Lotus_Write_File,Lotus.Real_Value,8);
  488.             end;
  489.  
  490.         Else
  491.             begin
  492.             end;
  493.         end;
  494.  
  495. end;
  496.  
  497. (****************************************************************)
  498.  
  499. Procedure Make_New_File_Name;
  500. var
  501.     DirName        : DirStr;
  502.     Fname        : NameStr;
  503.     Fext        : ExtStr;
  504. begin
  505.     FSplit(Lotus_Read_File_Name, DirName, Fname, Fext);
  506.     Lotus_Write_File_Name := DirName+Fname+'.WK!';
  507. end;
  508.  
  509. begin
  510. end.